# IMPORTING PACKAGES
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import warnings
warnings.filterwarnings ('ignore')
# IMPORTING CSV FILES
df = pd.read_csv("C:/Anaconda/PROJECTS/EAFC Data/all_players.csv")
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 17326 entries, 0 to 17325 Data columns (total 47 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Unnamed: 0 17326 non-null int64 1 Name 17326 non-null object 2 Nation 17326 non-null object 3 Club 17326 non-null object 4 Position 17326 non-null object 5 Age 17326 non-null int64 6 Overall 17326 non-null int64 7 Pace 17326 non-null int64 8 Shooting 17326 non-null int64 9 Passing 17326 non-null int64 10 Dribbling 17326 non-null int64 11 Defending 17326 non-null int64 12 Physicality 17326 non-null int64 13 Acceleration 17326 non-null int64 14 Sprint 17326 non-null int64 15 Positioning 17326 non-null int64 16 Finishing 17326 non-null int64 17 Shot 17326 non-null int64 18 Long 17326 non-null int64 19 Volleys 17326 non-null int64 20 Penalties 17326 non-null int64 21 Vision 17326 non-null int64 22 Crossing 17326 non-null int64 23 Free 17326 non-null int64 24 Curve 17326 non-null int64 25 Agility 17326 non-null int64 26 Balance 17326 non-null int64 27 Reactions 17326 non-null int64 28 Ball 17326 non-null int64 29 Composure 17326 non-null int64 30 Interceptions 17326 non-null int64 31 Heading 17326 non-null int64 32 Def 17326 non-null int64 33 Standing 17326 non-null int64 34 Sliding 17326 non-null int64 35 Jumping 17326 non-null int64 36 Stamina 17326 non-null int64 37 Strength 17326 non-null int64 38 Aggression 17326 non-null int64 39 Att work rate 17326 non-null object 40 Def work rate 17326 non-null object 41 Preferred foot 17326 non-null object 42 Weak foot 17326 non-null int64 43 Skill moves 17326 non-null int64 44 URL 17326 non-null object 45 Gender 17326 non-null object 46 GK 1952 non-null float64 dtypes: float64(1), int64(37), object(9) memory usage: 6.2+ MB
df.count()
Unnamed: 0 17326 Name 17326 Nation 17326 Club 17326 Position 17326 Age 17326 Overall 17326 Pace 17326 Shooting 17326 Passing 17326 Dribbling 17326 Defending 17326 Physicality 17326 Acceleration 17326 Sprint 17326 Positioning 17326 Finishing 17326 Shot 17326 Long 17326 Volleys 17326 Penalties 17326 Vision 17326 Crossing 17326 Free 17326 Curve 17326 Agility 17326 Balance 17326 Reactions 17326 Ball 17326 Composure 17326 Interceptions 17326 Heading 17326 Def 17326 Standing 17326 Sliding 17326 Jumping 17326 Stamina 17326 Strength 17326 Aggression 17326 Att work rate 17326 Def work rate 17326 Preferred foot 17326 Weak foot 17326 Skill moves 17326 URL 17326 Gender 17326 GK 1952 dtype: int64
df = df.drop(['GK'], axis = 1)
df.count()
Unnamed: 0 17326 Name 17326 Nation 17326 Club 17326 Position 17326 Age 17326 Overall 17326 Pace 17326 Shooting 17326 Passing 17326 Dribbling 17326 Defending 17326 Physicality 17326 Acceleration 17326 Sprint 17326 Positioning 17326 Finishing 17326 Shot 17326 Long 17326 Volleys 17326 Penalties 17326 Vision 17326 Crossing 17326 Free 17326 Curve 17326 Agility 17326 Balance 17326 Reactions 17326 Ball 17326 Composure 17326 Interceptions 17326 Heading 17326 Def 17326 Standing 17326 Sliding 17326 Jumping 17326 Stamina 17326 Strength 17326 Aggression 17326 Att work rate 17326 Def work rate 17326 Preferred foot 17326 Weak foot 17326 Skill moves 17326 URL 17326 Gender 17326 dtype: int64
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 17326 entries, 0 to 17325 Data columns (total 46 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Unnamed: 0 17326 non-null int64 1 Name 17326 non-null object 2 Nation 17326 non-null object 3 Club 17326 non-null object 4 Position 17326 non-null object 5 Age 17326 non-null int64 6 Overall 17326 non-null int64 7 Pace 17326 non-null int64 8 Shooting 17326 non-null int64 9 Passing 17326 non-null int64 10 Dribbling 17326 non-null int64 11 Defending 17326 non-null int64 12 Physicality 17326 non-null int64 13 Acceleration 17326 non-null int64 14 Sprint 17326 non-null int64 15 Positioning 17326 non-null int64 16 Finishing 17326 non-null int64 17 Shot 17326 non-null int64 18 Long 17326 non-null int64 19 Volleys 17326 non-null int64 20 Penalties 17326 non-null int64 21 Vision 17326 non-null int64 22 Crossing 17326 non-null int64 23 Free 17326 non-null int64 24 Curve 17326 non-null int64 25 Agility 17326 non-null int64 26 Balance 17326 non-null int64 27 Reactions 17326 non-null int64 28 Ball 17326 non-null int64 29 Composure 17326 non-null int64 30 Interceptions 17326 non-null int64 31 Heading 17326 non-null int64 32 Def 17326 non-null int64 33 Standing 17326 non-null int64 34 Sliding 17326 non-null int64 35 Jumping 17326 non-null int64 36 Stamina 17326 non-null int64 37 Strength 17326 non-null int64 38 Aggression 17326 non-null int64 39 Att work rate 17326 non-null object 40 Def work rate 17326 non-null object 41 Preferred foot 17326 non-null object 42 Weak foot 17326 non-null int64 43 Skill moves 17326 non-null int64 44 URL 17326 non-null object 45 Gender 17326 non-null object dtypes: int64(37), object(9) memory usage: 6.1+ MB
df.head()
| Unnamed: 0 | Name | Nation | Club | Position | Age | Overall | Pace | Shooting | Passing | ... | Stamina | Strength | Aggression | Att work rate | Def work rate | Preferred foot | Weak foot | Skill moves | URL | Gender | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | Kylian Mbappé | France | Paris SG | ST | 24 | 91 | 97 | 90 | 80 | ... | 88 | 77 | 64 | High | Low | Right | 4 | 5 | https://www.ea.com/games/ea-sports-fc/ratings/... | M |
| 1 | 1 | Erling Haaland | Norway | Manchester City | ST | 23 | 91 | 89 | 93 | 66 | ... | 76 | 93 | 87 | High | Medium | Left | 3 | 3 | https://www.ea.com/games/ea-sports-fc/ratings/... | M |
| 2 | 2 | Kevin De Bruyne | Belgium | Manchester City | CM | 32 | 91 | 72 | 88 | 94 | ... | 88 | 74 | 75 | High | Medium | Right | 5 | 4 | https://www.ea.com/games/ea-sports-fc/ratings/... | M |
| 3 | 3 | Lionel Messi | Argentina | Inter Miami CF | CF | 36 | 90 | 80 | 87 | 90 | ... | 70 | 68 | 44 | Low | Low | Left | 4 | 4 | https://www.ea.com/games/ea-sports-fc/ratings/... | M |
| 4 | 4 | Karim Benzema | France | Al Ittihad | CF | 35 | 90 | 79 | 88 | 83 | ... | 82 | 82 | 63 | Medium | Medium | Right | 4 | 4 | https://www.ea.com/games/ea-sports-fc/ratings/... | M |
5 rows × 46 columns
df.describe()
| Unnamed: 0 | Age | Overall | Pace | Shooting | Passing | Dribbling | Defending | Physicality | Acceleration | ... | Heading | Def | Standing | Sliding | Jumping | Stamina | Strength | Aggression | Weak foot | Skill moves | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | ... | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 | 17326.000000 |
| mean | 7308.093617 | 25.781658 | 66.980723 | 68.286448 | 54.803763 | 59.261284 | 56.852822 | 51.510216 | 65.663858 | 64.844049 | ... | 52.604006 | 47.898361 | 49.738255 | 47.244661 | 66.759206 | 63.733176 | 65.608623 | 56.614799 | 2.949786 | 2.419081 |
| std | 4814.849700 | 4.655255 | 6.981987 | 10.657137 | 13.872357 | 9.776640 | 19.041291 | 16.439490 | 9.485501 | 15.319163 | ... | 17.718303 | 20.692083 | 21.309042 | 20.771639 | 11.687863 | 16.440153 | 12.496360 | 16.892850 | 0.679713 | 0.794500 |
| min | 0.000000 | 17.000000 | 47.000000 | 27.000000 | 19.000000 | 25.000000 | 5.000000 | 15.000000 | 29.000000 | 14.000000 | ... | 5.000000 | 4.000000 | 8.000000 | 7.000000 | 27.000000 | 15.000000 | 22.000000 | 11.000000 | 1.000000 | 1.000000 |
| 25% | 2850.250000 | 22.000000 | 63.000000 | 62.000000 | 45.000000 | 53.000000 | 52.000000 | 37.000000 | 60.000000 | 57.000000 | ... | 45.000000 | 31.000000 | 30.000000 | 28.000000 | 59.000000 | 57.000000 | 58.000000 | 46.000000 | 3.000000 | 2.000000 |
| 50% | 7181.500000 | 25.000000 | 67.000000 | 69.000000 | 57.000000 | 60.000000 | 62.000000 | 55.000000 | 67.000000 | 68.000000 | ... | 56.000000 | 54.000000 | 58.000000 | 54.000000 | 68.000000 | 67.000000 | 67.000000 | 60.000000 | 3.000000 | 2.000000 |
| 75% | 11512.750000 | 29.000000 | 71.000000 | 76.000000 | 65.000000 | 66.000000 | 69.000000 | 65.000000 | 73.000000 | 75.000000 | ... | 65.000000 | 65.000000 | 67.000000 | 64.000000 | 75.000000 | 75.000000 | 74.000000 | 69.000000 | 3.000000 | 3.000000 |
| max | 15844.000000 | 43.000000 | 91.000000 | 97.000000 | 93.000000 | 94.000000 | 96.000000 | 91.000000 | 90.000000 | 97.000000 | ... | 94.000000 | 92.000000 | 92.000000 | 90.000000 | 95.000000 | 95.000000 | 96.000000 | 95.000000 | 5.000000 | 5.000000 |
8 rows × 37 columns
age_counts = df.groupby('Age')['Name'].count()
plt.figure(figsize=(12,8))
sns.barplot(x = age_counts.index, y = age_counts.values)
plt.title('Distribution of Age')
plt.xlabel('Age')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show
<function matplotlib.pyplot.show(close=None, block=None)>
# Create a histplot for the 'Overall' column
position = df['Overall'].value_counts
# Create a Seaborn histplot with specified bins
plt.figure(figsize=(12, 8))
sns.histplot(data=df, x='Overall', kde=True, bins=45) # Adjust the number of bins as needed
x_ticks = range(47, 92, 1) # Adjust the range and step as needed
plt.xticks(x_ticks)
plt.title('Distribution of Overall Rating')
plt.xlabel('Overall')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()
position_counts = df['Position'].value_counts(ascending=False)
# Create a Seaborn barplot
plt.figure(figsize=(12, 8))
sns.barplot(x = position_counts.index, y = position_counts.values) # Adjust the number of bins as needed
plt.title('Preferred Position Distribution')
plt.xlabel('Position')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()
# TOP 20 NATIONALITIES
nationality_counts = df['Nation'].value_counts(ascending=False).head(20)
# Create a Seaborn barplot
plt.figure(figsize=(12, 8))
sns.barplot(x = nationality_counts.index, y = nationality_counts.values) # Adjust the number of bins as needed
plt.title('Top 20 Nationalities')
plt.xlabel('Nationality')
plt.xticks(rotation = 45, ha = 'right')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()
# AVERAGE RATING PER POSITION
position_rating =df.groupby('Position')['Overall'].mean()
plt.figure(figsize=(12,8))
ax=sns.barplot(x = position_rating.index, y = position_rating.values)
plt.title('Average Rating per Position')
plt.xlabel('Position')
plt.xticks(rotation = 45, ha = 'right')
plt.ylabel('Overall Rating')
for p in ax.patches:
height = p.get_height()
rounded_percent = round(height) # Round to the nearest whole number
ax.annotate(f'{rounded_percent}', (p.get_x() + p.get_width() / 2., height),
ha='center', va='center', fontsize=9, color='black')
plt.tight_layout()
plt.show()
skill_columns = ['Shooting', 'Passing', 'Dribbling', 'Defending']
plt.figure(figsize=(12,6))
for skill in skill_columns:
sns.histplot(df[skill], kde=True, label=skill)
plt.title('Distribution of Skill Ratings')
plt.xlabel('Skill Rating')
plt.ylabel('Frequency')
plt.legend()
plt.show()
skill_columns = ['Shooting', 'Passing', 'Dribbling', 'Defending']
overall_rating = df['Overall']
#Create scatter plots for each skill rating against the overall player rating
plt.figure(figsize=(24,6))
for i, skill in enumerate(skill_columns, 1):
plt.subplot(1, len(skill_columns), i)
sns.regplot(x=df[skill], y=overall_rating, line_kws={"color": "red"}) # Use regplot for linear regression
plt.title(f'{skill} vs Overall Rating')
plt.xlabel(skill)
plt.ylabel('Overall Rating')
plt.tight_layout()
plt.show()
# Select relevant attributes for correlation analysis
attributes = df[['Pace', 'Shooting', 'Passing', 'Dribbling', 'Defending', 'Acceleration', 'Sprint', 'Physicality']]
# Calculate the correlation matrix
correlation_matrix = attributes.corr()
# Plot the heatmap to visualize the correlations
plt.figure(figsize=(12,8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f', square=True)
plt.title('Correlation Between Player Attributes')
plt.show()
foot_count = df['Preferred foot'].value_counts()
colors = ['#FA8072', '#4682b4']
explode = (0.1,0)
plt.figure(figsize = (8,8))
plt.pie(foot_count, labels=foot_count.index, autopct = '%1.1f%%', colors=colors, explode=explode, shadow=True)
plt.title('Preferred Foot Distribution')
plt.show()
gender_counts = df['Gender'].value_counts()
colors = ['#FA8072', '#4682b4']
explode = (0.2,0)
plt.figure(figsize=(8,8))
plt.pie(gender_counts, labels=gender_counts.index, autopct='%1.1f%%', colors=colors, explode=explode, shadow=True)
plt.title('Gender Distribution')
plt.show()
skill_columns = ['Att work rate', 'Def work rate']
plt.figure(figsize=(12,6))
for skill in skill_columns:
rate_count = df[skill].value_counts()
sns.histplot(df[skill], kde=True, label=skill)
plt.title('Distribution of Attacking and Defensive Work Rates')
plt.xlabel('Work Rate')
plt.ylabel('Frequency')
plt.legend()
plt.show
<function matplotlib.pyplot.show(close=None, block=None)>
# Define the order of the x-axis values
order = ['High', 'Medium', 'Low']
# Create the bar plot with the specified order
plt.figure(figsize=(8, 4))
sns.countplot(data=df, x='Att work rate', palette="Set2", order=order)
# Set labels and title
plt.xlabel('Attacking Work Rate')
plt.ylabel('Count')
plt.title('Count of Players by Attacking Work Rate')
# COUNT OF PLAYERS BY DEFENSIVE WORK RATE
# Create the bar plot with the specified order
plt.figure(figsize=(8, 4))
sns.countplot(data=df, x='Def work rate', palette="Set2", order=order)
# Set labels and title
plt.xlabel('Defensive Work Rate')
plt.ylabel('Count')
plt.title('Count of Players by Defensive Work Rate')
# Show the plot
plt.show()
# Combine 'Att work rate' and 'Def work rate' into 'Work Rate'
df['Work Rate'] = df['Att work rate'] + ' - ' + df['Def work rate']
# Create an interactive count plot using Plotly Express
fig = px.histogram(df, x='Work Rate', color='Gender', barmode='group',
title='Count of Work Rates by Gender', labels={'Work Rate': 'Work Rate'})
# Show the interactive plot
fig.show()
# WHO HAS THE MOVES? -- SKILL MOVE DISTRIBUTION
plt.figure(figsize=(12,6))
plot = sns.countplot(data = df, x='Skill moves', palette='Set1')
plt.title('Count of Skill Moves')
plt.xlabel('Skill Moves')
plt.ylabel('Count')
for p in plot.patches:
plot.annotate(f'{int(p.get_height())}', (p.get_x() + p.get_width() / 2., p.get_height()), ha='center', va='center', fontsize=8, color='black', xytext=(0,5), textcoords='offset points')
plt.show
<function matplotlib.pyplot.show(close=None, block=None)>
positions = ['CB', 'RB', 'LB', 'RWB', 'LWB', 'CDM']
#SCATTERPLOT
top_50_defenders = df.nlargest(50, ['Defending', 'Physicality'])
fig = px.scatter(top_50_defenders, x='Defending', y='Physicality', text='Name', title='Top 50 Players with Highest Defending and Physicality', color='Overall')
fig.update_traces(marker=dict(size=20))
fig.show()
#BARGRAPHs
top_50_players_by_defending = df[df['Position'].isin(positions)].nlargest(50, 'Defending')
top_50_players_by_physicality = df[df['Position'].isin(positions)].nlargest(50, 'Physicality')
fig_defending = px.bar(
top_50_players_by_defending,
x='Defending',
y='Overall',
title='Top 50 Defenders by Defense Rating',
color = 'Overall',
labels={'Defending', 'Defending'},
hover_data=['Name', 'Club', 'Nation', 'Position'],
hover_name='Name')
fig_physicality = px.bar(
top_50_players_by_physicality,
x='Physicality',
y='Overall',
title='Top 50 Defenders by Physicality Rating',
color = 'Overall',
labels={'Physicality', 'Physicality'},
hover_data=['Name', 'Club', 'Nation', 'Position'],
hover_name='Name')
fig_defending.show()
fig_physicality.show()
attributes = ['Pace', 'Shooting', 'Passing', 'Dribbling', 'Defending', 'Physicality']
average_values = df.groupby('Position')[attributes].mean().reset_index()
average_values[attributes] = average_values[attributes].apply(lambda x: round(x,2))
average_values
| Position | Pace | Shooting | Passing | Dribbling | Defending | Physicality | |
|---|---|---|---|---|---|---|---|
| 0 | CAM | 70.30 | 62.09 | 65.06 | 69.52 | 44.33 | 58.14 |
| 1 | CB | 59.71 | 37.28 | 50.80 | 48.62 | 67.25 | 72.09 |
| 2 | CDM | 61.93 | 52.81 | 62.15 | 62.32 | 64.93 | 70.09 |
| 3 | CF | 75.55 | 68.94 | 66.91 | 74.30 | 38.38 | 61.00 |
| 4 | CM | 66.19 | 59.24 | 65.26 | 67.01 | 59.27 | 64.95 |
| 5 | GK | 65.93 | 63.87 | 63.10 | 13.14 | 36.39 | 64.41 |
| 6 | LB | 72.86 | 46.55 | 59.16 | 62.93 | 62.70 | 65.28 |
| 7 | LM | 76.68 | 61.28 | 61.52 | 69.03 | 39.68 | 58.25 |
| 8 | LW | 78.20 | 64.07 | 62.95 | 71.82 | 37.45 | 58.69 |
| 9 | LWB | 73.65 | 47.39 | 57.94 | 62.24 | 59.61 | 65.17 |
| 10 | RB | 73.23 | 45.88 | 58.70 | 62.39 | 63.28 | 66.46 |
| 11 | RM | 77.22 | 60.42 | 61.40 | 68.44 | 41.00 | 59.01 |
| 12 | RW | 78.29 | 62.92 | 62.20 | 70.31 | 38.14 | 58.33 |
| 13 | RWB | 73.82 | 47.20 | 57.20 | 61.86 | 59.82 | 65.48 |
| 14 | ST | 70.55 | 66.56 | 55.22 | 65.25 | 31.66 | 67.09 |
#COMPARING THE BEST IN THE WORLD - FORWARDS
# Define the radar attributes and positions of interest
radar_attributes = ["Pace", "Shooting", "Passing", "Dribbling", "Defending", "Physicality"]
positions_of_interest = ['ST', 'RW', 'LW', 'CF']
# Filter the DataFrame for players with positions in the list
filtered_players = df[df['Position'].isin(positions_of_interest)]
# Calculate the average attributes for players in the specified positions
average_attributes = filtered_players[radar_attributes].mean()
# Sort the DataFrame to get the top 10 forwards by 'Overall'
top_10_forwards = filtered_players.nlargest(10, 'Overall')
# Create a subplot with two radar charts
fig = go.Figure()
# Create the first radar chart for average attributes
fig.add_trace(go.Scatterpolar(
r=average_attributes.values,
theta=average_attributes.index,
fill='toself',
name="Average Attributes"
))
# Create the second radar chart for the top 10 forwards by 'Overall'
for i, player in top_10_forwards.iterrows():
fig.add_trace(go.Scatterpolar(
r=player[radar_attributes].values,
theta=radar_attributes,
fill='toself',
name=player['Name'],
visible='legendonly' if i >= 10 else True # Only show legend for the top 10
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 100]
)
),
title='Comparison of Top 10 Forwards',
showlegend=True
)
# Add labels for each data point
for cat, val in zip(average_attributes.index, average_attributes.values):
fig.add_annotation(
text=f'Avg {cat}: {val:.2f}',
x=cat,
y=val,
showarrow=False
)
fig.show()
#COMPARING THE BEST IN THE WORLD - MIDFIELDERS
# Define the radar attributes and positions of interest
radar_attributes = ["Pace", "Shooting", "Passing", "Dribbling", "Defending", "Physicality"]
positions_of_interest = ['CM', 'RM', 'LM', 'CAM','CDM']
# Filter the DataFrame for players with positions in the list
filtered_players = df[df['Position'].isin(positions_of_interest)]
# Calculate the average attributes for players in the specified positions
average_attributes = filtered_players[radar_attributes].mean()
# Sort the DataFrame to get the top 10 forwards by 'Overall'
top_10_midfielders = filtered_players.nlargest(10, 'Overall')
# Create a subplot with two radar charts
fig = go.Figure()
# Create the first radar chart for average attributes
fig.add_trace(go.Scatterpolar(
r=average_attributes.values,
theta=average_attributes.index,
fill='toself',
name="Average Attributes"
))
# Create the second radar chart for the top 10 forwards by 'Overall'
for i, player in top_10_midfielders.iterrows():
fig.add_trace(go.Scatterpolar(
r=player[radar_attributes].values,
theta=radar_attributes,
fill='toself',
name=player['Name'],
visible='legendonly' if i >= 10 else True # Only show legend for the top 10
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 100]
)
),
title='Comparison of Top 10 Midfielders',
showlegend=True
)
# Add labels for each data point
for cat, val in zip(average_attributes.index, average_attributes.values):
fig.add_annotation(
text=f'Avg {cat}: {val:.2f}',
x=cat,
y=val,
showarrow=False
)
fig.show()
#COMPARING THE BEST IN THE WORLD - DEFENDERS
# Define the radar attributes and positions of interest
radar_attributes = ["Pace", "Shooting", "Passing", "Dribbling", "Defending", "Physicality"]
positions_of_interest = ['CB', 'LB', 'RB', 'LWB','RWB']
# Filter the DataFrame for players with positions in the list
filtered_players = df[df['Position'].isin(positions_of_interest)]
# Calculate the average attributes for players in the specified positions
average_attributes = filtered_players[radar_attributes].mean()
# Sort the DataFrame to get the top 10 forwards by 'Overall'
top_10_defenders = filtered_players.nlargest(10, 'Overall')
# Create a subplot with two radar charts
fig = go.Figure()
# Create the first radar chart for average attributes
fig.add_trace(go.Scatterpolar(
r=average_attributes.values,
theta=average_attributes.index,
fill='toself',
name="Average Attributes"
))
# Create the second radar chart for the top 10 forwards by 'Overall'
for i, player in top_10_defenders.iterrows():
fig.add_trace(go.Scatterpolar(
r=player[radar_attributes].values,
theta=radar_attributes,
fill='toself',
name=player['Name'],
visible='legendonly' if i >= 10 else True # Only show legend for the top 10
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 100]
)
),
title='Comparison of Top 10 Defenders',
showlegend=True
)
# Add labels for each data point
for cat, val in zip(average_attributes.index, average_attributes.values):
fig.add_annotation(
text=f'Avg {cat}: {val:.2f}',
x=cat,
y=val,
showarrow=False
)
fig.show()